package cn.llk.mall.service.impl;

import java.math.BigDecimal;

import cn.hutool.core.util.StrUtil;
import cn.llk.mall.dao.GoodsDao;
import cn.llk.mall.entity.GoodsEntity;
import cn.llk.mall.entity.GoodsOrderEntity;
import cn.llk.mall.entity.GoodsOrderItemEntity;
import cn.llk.mall.entity.UserEntity;
import cn.llk.mall.entity.vo.GoodsOrderVO;
import cn.llk.mall.service.GoodsOrderItemService;
import cn.llk.mall.service.GoodsOrderService;
import cn.llk.mall.service.GoodsService;
import cn.llk.mall.service.UserService;
import cn.llk.mall.util.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static cn.llk.mall.controller.api.GoodsController.cart_prefix;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author llk
 * @since 2021-04-20
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsDao, GoodsEntity> implements GoodsService {

    @Autowired
    UserService userService;
    @Autowired
    GoodsOrderService goodsOrderService;
    @Autowired
    GoodsOrderItemService goodsOrderItemService;

    @Override
    public IPage<GoodsEntity> findPage(long no, long size, String goodsName, String goodsType) {
        Page<GoodsEntity> page = new Page<>(no, size);
        QueryWrapper<GoodsEntity> qw = new QueryWrapper<>();
        if (StrUtil.isNotBlank(goodsName)) {
            qw.like("goods_name", goodsName);
        }
        if (StrUtil.isNotBlank(goodsType)) {
            qw.like("goods_type", goodsType);
        }
        return page(page, qw);
    }

    @Override
    public GoodsEntity checkStock(String goodsId, Integer count) {
        GoodsEntity dbGoods = getById(goodsId);
        Integer goodsStock = dbGoods.getGoodsStock() - count;
        // 库存不足够
        if (goodsStock < 0) return null;
        // 库存足够 直接购买
        dbGoods.setGoodsStock(goodsStock);
        dbGoods.setGoodsSaleCount(dbGoods.getGoodsSaleCount() + count);
        dbGoods.setUpdateDate(new Date());
        updateById(dbGoods);

        return dbGoods;
    }

    @Override
    public GoodsOrderVO buy(GoodsEntity goods, Integer count, UserEntity user) {
        // 保存订单
        GoodsOrderEntity order = initOrder(user);

        // 保存订单项
        GoodsOrderItemEntity orderItem = initOrderItem(goods, count, order);

        GoodsOrderVO goodsOrderVO = new GoodsOrderVO();
        goodsOrderVO.setOrder(order);
        goodsOrderVO.setOrderItems(Collections.singletonList(orderItem));
        order.setTotalMoney(goodsOrderVO.getOrderTotalMoney());

        goodsOrderItemService.save(orderItem);
        goodsOrderService.save(order);

        return goodsOrderVO;
    }

    private GoodsOrderItemEntity initOrderItem(GoodsEntity goods, Integer count, GoodsOrderEntity order) {
        GoodsOrderItemEntity orderItem = new GoodsOrderItemEntity();
        orderItem.setGoodsOrderId(order.getId());
        orderItem.setGoodsId(goods.getId());
        orderItem.setGoodsName(goods.getGoodsName());
        orderItem.setGoodsPrice(goods.getGoodsPrice());
        orderItem.setBuyCount(count);
        orderItem.setTotalPrice(goods.getGoodsPrice().multiply(BigDecimal.valueOf(count)));
        orderItem.setCreateDate(new Date());
        orderItem.setUpdateDate(new Date());
        orderItem.setGoodsImage(goods.getGoodsImage());
        return orderItem;
    }

    private GoodsOrderEntity initOrder(UserEntity user) {
        GoodsOrderEntity order = new GoodsOrderEntity();
        order.setId(UUID.randomUUID().toString());
        order.setUserId(user.getId());
        order.setUserName(user.getUserName());
        order.setCreateDate(new Date());
        order.setUpdateDate(new Date());
        return order;
    }


    @Autowired
    RedisUtil redisUtil;

    @Override
    public void putInCart(String goodsId, Integer count, UserEntity user) {
        String key = cart_prefix + user.getId();
        String hashKey = goodsId;
        Object value = redisUtil.hGet(key, hashKey);
        if (value == null || value.toString().equals("")) {
            value = 0;
        }
        value = count + Integer.parseInt(value.toString());

        redisUtil.hPut(key, hashKey, String.valueOf(value));
    }

    /**
     * 结算购物车
     *
     * @param goodsIdMapCount 商品id地图数
     * @param userId          用户id
     * @return {@link GoodsOrderVO}
     */
    @Override
    public GoodsOrderVO buyCart(Map<Object, Object> goodsIdMapCount, String userId) {
        GoodsOrderVO goodsOrderVO = new GoodsOrderVO();

        UserEntity dbUser = userService.getById(userId);
        GoodsOrderEntity order = initOrder(dbUser);  // 初始化order

        List<String> buySuccessOrderIds = new ArrayList<>(); // 购买成功的
        goodsOrderVO.setOrderItems(goodsIdMapCount.keySet().stream()
                .map((goodsId) -> {
                    Integer count = Integer.valueOf(goodsIdMapCount.get(goodsId).toString());
                    GoodsEntity goods = checkStock(goodsId.toString(), count);
                    if (goods == null) {
                        return null;
                    }
                    buySuccessOrderIds.add(goodsId.toString());
                    GoodsOrderItemEntity orderItem = initOrderItem(
                            goods, // goods
                            count, // count
                            order);
                    goodsOrderItemService.save(orderItem);
                    return orderItem;
                }).filter(Objects::nonNull).collect(Collectors.toList()));

        goodsOrderVO.setOrder(order);
        order.setTotalMoney(goodsOrderVO.getOrderTotalMoney());
        // 保存订单信息
        goodsOrderService.save(order);
        // 清空购买成功的购物车
        redisUtil.hDelete(cart_prefix + userId, buySuccessOrderIds.toArray());

        return goodsOrderVO;
    }

    @Override
    public GoodsOrderVO getCart(Map<Object, Object> goodsIdMapCount, String userId) {
        GoodsOrderVO goodsOrderVO = new GoodsOrderVO();

        UserEntity dbUser = userService.getById(userId);
        GoodsOrderEntity order = initOrder(dbUser);  // 初始化order
        goodsOrderVO.setOrderItems(goodsIdMapCount.keySet().stream()
                .map((goodsId) -> initOrderItem(
                        getById(goodsId.toString()), // goods
                        Integer.valueOf(goodsIdMapCount.get(goodsId).toString()), // count
                        order)).collect(Collectors.toList()));

        goodsOrderVO.setOrder(order);
        order.setTotalMoney(goodsOrderVO.getOrderTotalMoney());
        return goodsOrderVO;
    }
}
